package cn.sjx.print.util;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.map.MapUtil;
import cn.hutool.core.util.PageUtil;
import cn.hutool.core.util.ReUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HtmlUtil;
import cn.sjx.print.constants.PrintConstant;
import cn.sjx.print.entity.HtmlRenderData;
import cn.sjx.print.service.BaseRenderFactoryHandler;
import cn.sjx.print.service.customer.JasperReportParametersCover;
import cn.sjx.print.service.customer.JasperReportRenderHtmlHandler;
import cn.sjx.print.service.customer.impl.JasperReportRenderHtmlHandlerDefaultImpl;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import lombok.extern.slf4j.Slf4j;
import net.sf.jasperreports.engine.export.HtmlExporter;
import net.sf.jasperreports.export.SimpleExporterInput;
import net.sf.jasperreports.export.SimpleHtmlExporterOutput;
import org.beetl.core.Configuration;
import org.beetl.core.GroupTemplate;
import org.beetl.core.Template;
import org.beetl.core.resource.ClasspathResourceLoader;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

/**
 * html渲染工厂
 *
 * @author sjx
 * @date 2020年05月12日 16:28:33
 */
@Slf4j
public class HtmlRenderFactoryUtil extends BaseRenderFactoryHandler {

    /**
     * 套打模式渲染
     * 自定义数据并渲染为模板
     *
     * @param templateName    模板名称
     * @param htmlRenderData  填充数据（若dataList为空，则采用druid数据源）
     * @param subTemplateName 子模板名称（在jasperReport中，添加相同个数名称为“SUB_REPORT_[0，1，2......]”；Class属性为“net.sf.jasperreports.engine.JasperReport”的Parameters参数）
     * @return {@link String}
     */
    public static List<String> renderList(String templateName, HtmlRenderData htmlRenderData, int pageDataSize,
                                          String... subTemplateName) {
        return renderList(templateName, htmlRenderData, pageDataSize, null, subTemplateName);
    }

    /**
     * 套打模式渲染
     * 自定义数据并渲染为模板
     *
     * @param templateName    模板名称
     * @param htmlRenderData  填充数据（若dataList为空，则采用druid数据源）
     * @param pageDataSize    每页打印数据量
     * @param customerDataFun 自定义每页的数据（htmlRenderData）
     * @param subTemplateName 子模板名称（在jasperReport中，添加相同个数名称为“SUB_REPORT_[0，1，2......]”；Class属性为“net.sf.jasperreports.engine.JasperReport”的Parameters参数）
     * @return {@link String}
     */
    public static List<String> renderList(String templateName, HtmlRenderData htmlRenderData, int pageDataSize,
                                          JasperReportParametersCover<HtmlRenderData> customerDataFun, String... subTemplateName) {
        List<String> htmlList = new ArrayList<String>(0);

        try {
            if (null == htmlRenderData) {
                throw new Exception("模板渲染数据不能为空！");
            }

            Map<String, Object> parametersMap = htmlRenderData.getParamMap();
            List<Map<String, ?>> dataList = htmlRenderData.getDataList();

            if (CollectionUtil.isEmpty(dataList)) {
                return htmlList;
            }

            // 计算总数量
            int totalCount = PageUtil.totalPage(dataList.size(), pageDataSize);
            htmlList = new ArrayList<String>(totalCount);

            for (int i = 0; i < totalCount; i++) {
                int[] pageStartEndArray = PageUtil.transToStartEnd(i + 1, pageDataSize);
                HtmlRenderData tempHtmlRenderData = new HtmlRenderData(parametersMap,
                        CollUtil.sub(dataList, pageStartEndArray[0], pageStartEndArray[1]));

                // 用户自己修改HtmlRenderData
                if (null != customerDataFun) {
                    tempHtmlRenderData = customerDataFun.cover(tempHtmlRenderData);
                }

                // 生成单个html
                htmlList.add(render(templateName, tempHtmlRenderData, subTemplateName));
            }
        } catch (Exception e) {
            log.error("======> 套打html生成失败，原因：", e);
        }

        return htmlList;
    }

    /**
     * 渲染（使用默认html处理程序）
     * 自定义数据并渲染为模板
     *
     * @param templateName    模板名称
     * @param htmlRenderData  填充数据（若dataList为空，则采用druid数据源）
     * @param subTemplateName 子模板名称（在jasperReport中，添加相同个数名称为“SUB_REPORT_[0，1，2......]”；Class属性为“net.sf.jasperreports.engine.JasperReport”的Parameters参数）
     * @return {@link String}
     */
    public static String render(String templateName, HtmlRenderData htmlRenderData, String... subTemplateName) {
        return render(templateName, htmlRenderData, new JasperReportRenderHtmlHandlerDefaultImpl(), subTemplateName);
    }

    /**
     * 渲染（自定义html处理程序）
     * 自定义数据并渲染为模板
     *
     * @param templateName    模板名称
     * @param htmlRenderData  填充数据（若dataList为空，则采用druid数据源）
     * @param htmlHandler     html处理程序
     * @param subTemplateName 子模板名称（在jasperReport中，添加相同个数名称为“SUB_REPORT_[0，1，2......]”；Class属性为“net.sf.jasperreports.engine.JasperReport”的Parameters参数）
     * @return {@link String}
     */
    public static String render(String templateName, HtmlRenderData htmlRenderData, JasperReportRenderHtmlHandler htmlHandler,
                                String... subTemplateName) {
        // 定义最终返回结果
        StringBuffer resultRenderBuffer = new StringBuffer();
        try {
            // 导出为html
            HtmlExporter htmlExporter = new HtmlExporter();
            htmlExporter.setExporterInput(new SimpleExporterInput(generateJasperPrint(templateName, htmlRenderData,
                    subTemplateName)));
            htmlExporter.setExporterOutput(new SimpleHtmlExporterOutput(resultRenderBuffer));
            htmlExporter.exportReport();
        } catch (Exception e) {
            log.error("======> 模板渲染出错，原因：", e);
        }

        return htmlHandler.handle(resultRenderBuffer.toString());
    }

    /**
     * 渲染（beetl模板渲染）
     *
     * @param templateName 模板名称
     * @param dataMap      数据地图
     * @return {@link String }
     * @author sjx
     * @date 2020年09月30日 16:24:01
     */
    public static String render(String templateName, Map<String, Object> dataMap) {
        String html = "";
        try {
            if (StrUtil.isBlank(templateName) || MapUtil.isEmpty(dataMap)) {
                throw new Exception("模板名或数据不能为空......");
            }

            // 参数不为空,进行反转义处理
            if (MapUtil.isNotEmpty(dataMap) &&
                    PrintConstant.PRINT_CONFIG_SETTING.getBool(PrintConstant.PRINT_CONFIG_PRINT_DATA_UNESCAPE)) {
                String dataMapStr = JSON.toJSONString(dataMap);
                dataMap = JSON.parseObject(HtmlUtil.unescape(dataMapStr), new TypeReference<Map<String, Object>>() {
                }.getType());
            }

            GroupTemplate groupTemplate = new GroupTemplate(new ClasspathResourceLoader(PrintConstant.TEMPLATE_FILE_PREFIX),
                    Configuration.defaultConfiguration());
            Template template = groupTemplate.getTemplate(templateName);
            template.binding(dataMap);
            html = template.render();
        } catch (Exception e) {
            log.error("======> beetl渲染出错", e);
        }

        // 去除换行符
        return html
                // 单引号转义
                .replaceAll("\'", "\\\\'")
                // 去除换行符
                .replaceAll("\\r\\n", "");
    }

}